package com.onpositive.data.diskstorage;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;

import com.onpositive.data.AbstractReader;
import com.onpositive.data.IPropertyMetadata;
import com.onpositive.data.IReadableObjectCollection;
import com.onpositive.data.ISeekableAccess;
import com.onpositive.data.serializer.readers.DefaultReaderFactory;
import com.onpositive.data.serializer.readers.RemoteByteArrayReader;
import com.onpositive.data.serializer.readers.RemoteByteArrayReader.Downloader;

public abstract class SplittedCollection extends AbstractObjectCollection implements IReadableObjectCollection<Integer>{
	

	public SplittedCollection(int dataSize) {
		super(dataSize);
	}
	
	ArrayList<ReaderInfo>infos=new ArrayList<SplittedCollection.ReaderInfo>();
	
	
	public SplittedCollection (byte[] str) throws IOException, ClassNotFoundException{
		super(0);
		GZIPInputStream ss=new GZIPInputStream(new ByteArrayInputStream(str));
		DataInputStream str2 = new DataInputStream(ss);
		str2.readInt();
		dataSize=str2.readInt();
		init(str2);
	}
	
	public SplittedCollection(DataInputStream str) throws IOException, ClassNotFoundException{
		super(str.readInt());
		init(str);
	}

	public void init(DataInputStream str) throws IOException,
			ClassNotFoundException {
		str.readLong();
		int readInt = str.readInt();
		for (int a=0;a<readInt;a++){
			String id=str.readUTF();
			int k=str.readInt();
			StoredMetadata m=new StoredMetadata();
			m.setId(id);
			for (int b=0;b<k;b++){
				m.setVlaue(str.readUTF(), str.readUTF());
			}			
			addMetadata(m);
		}
		ByteBufferSeekableAcess access = new ByteBufferSeekableAcess(null);
		for (int a=0;a<readInt;a++){
			int type=str.readInt();
			int start=str.readInt();
			int length=str.readInt();
			infos.add(new ReaderInfo(start, start+length, type, access));
		}
		int readInt2 = str.readInt();
		byte[] buf = new byte[readInt2-1];
		access.buf=buf;
		access.seek(0);
		str.readFully(buf);
		str.close();
	}
	
	protected static class ReaderInfo{
		public ReaderInfo(int start, int end, int type, ISeekableAccess access) {
			super();
			this.start = start;
			this.end = end;
			this.type = type;
			this.access = access;
		}
		protected String extra;
		protected final int start;
		protected final int end;
		protected final int type;
		protected final ISeekableAccess access;
	}
	
	

	@Override
	protected AbstractReader<?> initReader(IPropertyMetadata meta) {
		ReaderInfo l=getAccess(meta);
		if (l.start<0){
			return new RemoteByteArrayReader(Object.class,getCache(meta),getDownloader(meta)) ;
		}
		AbstractReader<?> createReader = DefaultReaderFactory.getInstance().createReader(l.type,meta);
		createReader.setFile(l.access);
		createReader.setMyStart(l.start);
		createReader.setMyEnd(l.end);
		
		recordReader(meta, createReader);
		return createReader;
	}

	protected abstract Downloader getDownloader(IPropertyMetadata meta);

	protected abstract File getCache(IPropertyMetadata m) ;

	protected ReaderInfo getAccess(IPropertyMetadata meta) {
		Integer integer = metadataIndexMap.get(meta);
		return infos.get(integer);		
	}


	
}